#ifndef __MEMORYTRACER_H__
#define __MEMORYTRACER_H__

#include <map>

namespace xgu{

using std::map;

// ----------------- Memory Tracer ---------------------- //

class MemoryTracer
{
public:
	~MemoryTracer();

	void add(void* ptr, const char* file, int line);
	void erase(void* ptr);

	static MemoryTracer* getInstance() 
		{ return &instance; }

private:
	MemoryTracer();

	static MemoryTracer instance;

private:
	struct Record
	{
		Record* flink, *blink;

		void* ptr;
		const char* file;
		int line;
	};
	Record head;
};

}

/**************************************************************/

inline void* __cdecl operator new(size_t cbSize, const char* file, int line)
{
	void* ptr = malloc(cbSize);
	xgu::MemoryTracer::getInstance()->add(ptr, file, line);
	return ptr;
}

inline void* __cdecl operator new[](size_t cbSize, const char* file, int line)
{
	void* ptr = malloc(cbSize);
	xgu::MemoryTracer::getInstance()->add(ptr, file, line);
	return ptr;
}

inline void	__cdecl operator delete(void * object, const char*, int)
{
	if (object)
	{
		xgu::MemoryTracer::getInstance()->erase(object);
		free(object);
	}
}

inline void	__cdecl operator delete[](void * object, const char*, int)
{
	if (object)
	{
		xgu::MemoryTracer::getInstance()->erase(object);
		free(object);
	}
}

inline void __cdecl operator delete(void* ptr)
	{ operator delete(ptr, NULL, 0); }

inline void __cdecl operator delete[](void* ptr)
	{ operator delete(ptr, NULL, 0); }

#ifndef _NDEBUG
#	define DEBUG_NEW new(__FILE__, __LINE__)
#else
#	define DEBUG_NEW new
#endif

#define new DEBUG_NEW

#endif // __MEMORYTRACER_H__

